package resource

import (
	"fmt"
	"gitee.com/whilew/gen-go/pkg/util"
	"reflect"
	"strings"
)

type ModelInfo struct {
	Name    string       // 名称
	Fields  []*FieldInfo // 字段
	Comment string       // 注释
}

type FieldInfo struct {
	Name    string            // 名称
	Type    string            // 类型
	Comment string            // 注释
	Tag     reflect.StructTag `pk:"true"` // 标签
}

func appendTag(stag reflect.StructTag, key, value string) reflect.StructTag {
	tag := string(stag)
	if tag != "" {
		tag += " "
	}
	tag += fmt.Sprintf("%s:\"%s\"", key, value)
	return reflect.StructTag(tag)
}

func convertToFieldInfo(dbColumns []*util.DbColumn) []*FieldInfo {
	var result []*FieldInfo
	for _, c := range dbColumns {
		field := &FieldInfo{
			Name:    c.ColumnName,
			Type:    c.GetDataType(),
			Comment: c.ColumnComment,
		}
		if c.IsPrimaryKey() {
			field.Tag = appendTag(field.Tag, "pk", "true")
		}
		if field.Comment != "" && strings.HasPrefix(field.Comment, "uuid ") {
			field.Tag = appendTag(field.Tag, "uuid", "true")
			//field.Comment = strings.TrimPrefix(field.Comment, "uuid ")
		}
		result = append(result, field)
	}
	return result
}

// SetModeInfoByMySqlDsn TODO 需要优化
func SetModeInfoByMySqlDsn(dsn string, tablePrefix []string, withoutPrefix []string) VisitorFunc {
	return func(info *Info, err error) error {
		db, err := util.ConnectDB(dsn)
		if err != nil {
			return fmt.Errorf("connect db fail: %w", err)
		}
		tables, err := db.Migrator().GetTables()
		if err != nil {
			return fmt.Errorf("gorm migrator get all tables fail: %w", err)
		}
		var models []*ModelInfo
		for _, tableName := range tables {
			if len(tablePrefix) > 0 {
				if !util.IsPrefix(tableName, tablePrefix) {
					continue
				}
			}
			if len(withoutPrefix) > 0 {
				if util.IsPrefix(tableName, withoutPrefix) {
					continue
				}
			}
			m := &ModelInfo{
				Name: tableName,
			}
			dbColumn, err := util.GetDbColumns(db, db.Migrator().CurrentDatabase(), tableName)
			if err != nil {
				return fmt.Errorf("get table %s columns fail: %w", tableName, err)
			}
			m.Fields = convertToFieldInfo(dbColumn)
			models = append(models, m)
		}
		info.Models = models
		return nil
	}
}
